#include <stdbool.h>
#include <string.h>
#include "at32_sdio.h"
#include "bsp_board.h"
#include "at32f435_437_clock.h"
#include "ff.h"
#include "app_menu.h"
#include "app_file.h"
#include "app_iap.h"


/* 全局变量 */
app_file_t 	g_app_file;
uint8_t 	g_state;
uint8_t     g_buff[APP_FILE_PACKET_LEN];
uint32_t 	g_load_addr = 0;







#define STATE_INIT		0
#define STATE_MCU_AT32	1
#define STATE_MCU_AC63	2
#define STATE_JUMP		3


/**
  * @brief  configures sdio1 irq channel.
  * @param  none
  * @retval none
  */
static void nvic_configuration(void)
{
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  nvic_irq_enable(SDIO1_IRQn, 1, 1);
}


/**
***********************************************************
* @brief	上电状态 
* @param 
* @return 
***********************************************************
*/
static void fun_init(uint8_t *state)
{
	/* 切换页面到上电状态 */
	menu_change(MENU_UBOOT_VERSION);

	/* 查找文件 */
	app_file_find(&g_app_file);

	/* 判断是否有可升级文件 */
	if((g_app_file.count > 0) && g_app_file.is_at32_up)
	{
		*state = STATE_MCU_AT32;
	}
	else if((g_app_file.count > 0) && g_app_file.is_ac63_up)
	{
		*state = STATE_MCU_AC63;
	}
	else
	{
		menuTask();	
		bsp_delay_ms(1000);
		DBG_log("No upgrade files");
		app_load(0x08001000);
	}
	
}
/**
***********************************************************
* @brief	更新AT32 MCU 
* @param 	状态指针
* @return 
***********************************************************
*/
static void fun_mcu_at32(uint8_t *state)
{
	up_file_info_t *info;
	uint32_t write_addr = 0;
	uint8_t  schedule = 0;
	uint8_t res = 0;
	uint8_t temp[2] = {0};
	/* 切换页面 */
	menu_change(MENU_UBOOT_UPDATE);
	
	/* 解析升级文件 */
	info = g_app_file.up_file_info[0];
	g_load_addr = be32_to_cpu(g_app_file.ih_file->ih_load);
	DBG_log("load_addr:0x%x",g_load_addr);
	while(1)
	{
		/* 读取文件 */
		res = app_file_read(&g_app_file,g_buff);
		if(res == FR_OK)
		{
			info->cur_packet_index++;

			/* 计算进度 */
			schedule =  (info->cur_packet_index  * 100) / info->total_packet_count;
//			DBG_log("cur packet index:%d schedule:%d\%",info->cur_packet_index, schedule);

			/* 刷新显示 */
			temp[0] = schedule;
			menu_set_schedule(temp);
			menuTask();
			
			/* 写入文件 */
			write_addr = g_load_addr + (info->cur_packet_index - 1) * APP_FILE_PACKET_LEN;
			DBG_log("index:%d write addr:0x%x",info->cur_packet_index, write_addr);
			app_flash_2kb_write(write_addr, g_buff);

			/* 清空缓存 */
			memset(g_buff,0x00,sizeof(g_buff));
			if(info->cur_packet_index == info->total_packet_count)
			{
				if(g_app_file.count > 1) // 没有ac63升级文件
				{
					*state = STATE_MCU_AC63;	
				}
				else
				{
					*state = STATE_JUMP;
				}
				
				return ;
			}
			
		}
		
	}
	
}
/**
***********************************************************
* @brief	更新AC63 MCU 
* @param 	状态指针
* @return 
***********************************************************
*/
static void fun_mcu_ac63(uint8_t *state)
{
	bsp_delay_ms(500);
	DBG_log("updata mcu ac63");
	while(1)
	{

	}
}
/**
***********************************************************
* @brief	跳转用户程序 
* @param 
* @return 
***********************************************************
*/
static void	fun_mcu_jump(uint8_t *state)
{
	*state = STATE_INIT;
	app_load(g_load_addr);
}

/* gloable functions ---------------------------------------------------------*/
/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{
	
	system_clock_config();
	nvic_configuration();
	bsp_board_init();
	while(1)
	{
		switch(g_state)
		{
			case STATE_INIT:
				fun_init(&g_state);
				break;
			case STATE_MCU_AT32:
				fun_mcu_at32(&g_state);
				break;
			case STATE_MCU_AC63:
				fun_mcu_ac63(&g_state);
				break;
			case STATE_JUMP:
				fun_mcu_jump(&g_state);
				break;
			default:

				break;
				
		}
		bsp_delay_ms(500);
		menuTask();	
	}

}


